package com.wars2d.client;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Input.Keys;
import com.badlogic.gdx.InputProcessor;
import com.badlogic.gdx.files.FileHandle;
import com.badlogic.gdx.graphics.GL10;
import com.badlogic.gdx.graphics.Pixmap;
import com.badlogic.gdx.graphics.Pixmap.Format;
import com.badlogic.gdx.graphics.g2d.BitmapFont;
import com.badlogic.gdx.graphics.g2d.TextureAtlas;
import com.badlogic.gdx.graphics.g2d.TextureRegion;
import com.badlogic.gdx.scenes.scene2d.Actor;
import com.badlogic.gdx.scenes.scene2d.Stage;

public class GameStage extends Stage implements InputProcessor {
	
	
	

	static class StaticObject {
		float x, y;
		
		int id;
		
		public StaticObject(int id, float x, float y) {
			this.x = x;
			this.y = y;
			
			this.id = id;
		}
	}
	
	boolean jumpPressed = false;
	
	public static final int ID_GROUND 	= 0x0000ff;
	public static final int ID_AIR 		= 0x00ff00;
	public static final int	ID_PLAYER 	= 0xff0000;
	
	PlayerActor mPlayer = null;

	
//	ArrayList<StaticObject> mActorList = new ArrayList<StaticObject>();
	
	int[][] mActors = null;
	
	HashMap<Integer, TextureRegion> mObjIdToTextureMap = new HashMap<Integer, TextureRegion>();
	
	BitmapFont mFont = null;
	
	int pixelXPerBlock = 32;
	int pixelYPerBlock = 32;
	
	int mapBlockCountX;
	int mapBlockCountY;
	
	int mapWidth;
	int mapHeight;
	
	float cameraX = 0;
	float cameraY = 0;
	
	int camW;
	int camH;
	
	
	
	int currentBlockX = 0;
	int currentBlockY = 0;
	
	int lastBlockX = 0;
	int lastBlockY = 0;

	
	int blocksInX = Global.SCREEN_WIDTH / pixelXPerBlock;
	int blocksInY = Global.SCREEN_HEIGHT / pixelYPerBlock;

	
	public void addTextureRegion(int id, TextureRegion region) {
		if (!mObjIdToTextureMap.containsKey(id)) {
			mObjIdToTextureMap.put(id, region);
		}
	}
	
	public void addActor(int id, int x, int y) {
//		mActorList.add(new StaticObject(id, x, y));
		mActors[y][x] = id;
	}
	
	public GameStage(float width, float height, boolean stretch) {
		super(width, height, stretch);
		
		mFont = new BitmapFont();
		
		FileHandle mapFile = Gdx.files.internal("data/level1/level.png");
		
		TextureAtlas mAtlas = new TextureAtlas(Gdx.files.internal("data/level1/pack"));
		
		addTextureRegion(ID_GROUND, mAtlas.findRegion(nameOf(ID_GROUND)));
		addTextureRegion(ID_AIR, mAtlas.findRegion(nameOf(ID_AIR)));
		addTextureRegion(ID_PLAYER, mAtlas.findRegion(nameOf(ID_PLAYER)));
		
		mPlayer = new PlayerActor(this, mAtlas.findRegion("player"));
		
		addActor(mPlayer);
		
		Pixmap mMap = new Pixmap(mapFile);
		
		mapBlockCountX 	= mMap.getWidth();
		mapBlockCountY	= mMap.getHeight();
		
		if (blocksInX > mapBlockCountX)
			blocksInX = mapBlockCountX;

		if (blocksInY > mapBlockCountY)
			blocksInY = mapBlockCountY;

		
		mapWidth 	= (int) (mapBlockCountX * pixelXPerBlock);
		mapHeight 	= (int) (mapBlockCountY * pixelYPerBlock);
		
		camW = (int) (32 * pixelXPerBlock);
		camH = (int) (32 * pixelYPerBlock);
		
		mActors = new int[mapBlockCountX][mapBlockCountY];
		
		Format pixelFormat = mMap.getFormat();
		
		if (pixelFormat != Format.RGB888) {
			throw new RuntimeException("format must be RGB888");
		}
		
		for (int i = 0; i < mapBlockCountY; ++i) {
			for (int j = 0; j < mapBlockCountX; ++j) {
				int pixel = (mMap.getPixel(j, i) & 0xffffff00) >>> 8;
				
				switch (pixel) {
				case ID_GROUND:
					addActor(ID_GROUND, j, mapBlockCountY - i - 1);
					break;
					
				case ID_AIR:
					addActor(ID_AIR, j, mapBlockCountY - i - 1);
					break;
					
				case ID_PLAYER:
					mPlayer.x = j * pixelXPerBlock;
					mPlayer.y = (mapBlockCountY - i - 1) * pixelYPerBlock;
					addActor(ID_AIR, j, mapBlockCountY - i - 1);
					break;
				}
			}
		}
		
		Gdx.input.setInputProcessor(this);
	}
	
	private String nameOf(int id) {
		switch (id) {
		case ID_GROUND:
			return "ground";
		
		case ID_AIR:
			return "air";
		}
		
		return null;
	}

	@Override
	public void draw() {
		super.draw();
		
		Gdx.gl.glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
		Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT);
		
		camera.update();
		camera.apply(Gdx.gl10);
		
		float deltaTime = Gdx.graphics.getDeltaTime();
		
		batch.begin();
		
		currentBlockX = (int) (camera.position.x - camera.viewportWidth / 2) / pixelXPerBlock;
		currentBlockY = (int) (camera.position.y - camera.viewportHeight / 2) / pixelYPerBlock;
		
		lastBlockX = (int) (camera.position.x + camera.viewportWidth / 2) / pixelXPerBlock + 1;
		lastBlockY = (int) (camera.position.y + camera.viewportHeight / 2) / pixelYPerBlock + 1;
		
		if (currentBlockX < 0) {
			currentBlockX = 0;
		}
		
		if (currentBlockY < 0) {
			currentBlockY = 0;
		}
		
		if (lastBlockX > mapBlockCountX) {
			lastBlockX = mapBlockCountX - 1;
		}

		if (lastBlockY > mapBlockCountY) {
			lastBlockY = mapBlockCountY - 1;
		}


		for (int i = currentBlockY; i < lastBlockY; ++i) {
			for (int j = currentBlockX; j < lastBlockX; ++j) {
				TextureRegion texture = mObjIdToTextureMap.get(mActors[i][j]);
				
				if (texture == null)
					continue;
				
				batch.draw(texture, j * pixelXPerBlock, i * pixelYPerBlock);
			}
		}
		
		mFont.draw(batch, "fps : " + Gdx.graphics.getFramesPerSecond(), 100 + camera.position.x, 100 + camera.position.y);
		
		List<Actor> actors = getActors();
		
		for (Actor actor : actors) {
			actor.draw(batch, Gdx.graphics.getDeltaTime());
		}
		
		batch.end();
		
		 
		if (Gdx.input.isKeyPressed(Keys.DPAD_RIGHT)) {
			camera.position.x += pixelXPerBlock;
//			currentBlockX++;
		} else if (Gdx.input.isKeyPressed(Keys.DPAD_LEFT)) {
			camera.position.x -= pixelXPerBlock;
//			currentBlockX--;
		} else if (Gdx.input.isKeyPressed(Keys.DPAD_UP)) {
			camera.position.y += pixelYPerBlock;
//			currentBlockY++;
		} else if (Gdx.input.isKeyPressed(Keys.DPAD_DOWN)) {
			camera.position.y -= pixelYPerBlock;
//			currentBlockY--;
		}
		
		if (Gdx.input.isKeyPressed(Keys.D)) {
			mPlayer.goToRight(1000, deltaTime);
		} else if (Gdx.input.isKeyPressed(Keys.A)) {
			mPlayer.goToLeft(1000, deltaTime);
		} else if (Gdx.input.isKeyPressed(Keys.S)) {
			mPlayer.y -= 3;
		}
		
		camera.position.x = mPlayer.x;
		camera.position.y = mPlayer.y;
		
		System.out.println("camX : " + camera.position.x + " camY : " + camera.position.y);
		
//		if (camera.position.x < blocksInX * pixelXPerBlock / 2)
//			camera.position.x = blocksInX * pixelXPerBlock / 2;
//
//		if (camera.position.y < blocksInY * pixelYPerBlock / 2)
//			camera.position.y = blocksInY * pixelYPerBlock / 2;
//
//		if (camera.position.x > Global.SCREEN_WIDTH - blocksInX * pixelXPerBlock / 2)
//			camera.position.x = Global.SCREEN_WIDTH - blocksInX * pixelXPerBlock / 2;
//
//		if (camera.position.y > Global.SCREEN_HEIGHT - blocksInY * pixelYPerBlock / 2)
//			camera.position.y = Global.SCREEN_HEIGHT - blocksInY * pixelYPerBlock / 2;
//		
		
		
//		currentBlockX = (int) (mPlayer.x / pixelXPerBlock) - blocksInX / 2;
//		currentBlockY = (int) (mPlayer.y / pixelYPerBlock) - blocksInY / 2;
//		
//		if (currentBlockX < 0)
//			currentBlockX = 0;
//		
//		if (currentBlockX + blocksInX + 2 >= mapBlocksX)
//			currentBlockX = mapBlocksX - blocksInX - 2;
//
//		if (currentBlockY < 0)
//			currentBlockY = 0;
//		
//		if (currentBlockY + blocksInY + 2 >= mapBlocksY)
//			currentBlockY = mapBlocksY - blocksInY - 2;

	}
	
	@Override
	public void act(float delta) {
		super.act(delta);
		
		mPlayer.act(delta);
	}

	public boolean isGround(int x, int y) {
		if (x  < 0 || y < 0)
			return true;
		
		return mActors[y][x] == ID_GROUND;
	}
	
	public boolean canGo(float x, float y, float w, float h) {
		
//		if (x < 0 || y > 0 || x > Global.SCREEN_WiDTH || y > Global.SCREEN_HEIGHT) {
//			return false;
//		}
		 
		int corner1X = (int) (x / pixelXPerBlock);
		int corner1Y = (int) (y / pixelYPerBlock);
		
		if (isGround(corner1X, corner1Y)) {
			return false;
		} else {
			int corner2X = (int) (x / pixelXPerBlock);
			int corner2Y = (int) ((y + h) / pixelYPerBlock);
			
			if (isGround(corner2X, corner2Y)) {
				return false;
			} else {
				int corner3X = (int) ((x + w) / pixelXPerBlock);
				int corner3Y = (int) ((y + h) / pixelYPerBlock);
				
				if (isGround(corner3X, corner3Y)) {
					return false;
				} else {
					int corner4X = (int) ((x + w) / pixelXPerBlock);
					int corner4Y = (int) (y / pixelYPerBlock);
					
					if (isGround(corner4X, corner4Y)) {
						return false;
					}
				}
			}
		}
		
		return true;
	}
	
	@Override
	public boolean keyDown(int keycode) {
		
		switch (keycode) {
		case Keys.W:
			mPlayer.tryJump();
			break;
		}
		return true;
	}
	
	

}
